package com.dotflat.fin.controller;

import com.alibaba.fastjson.JSON;
import com.dotflat.fin.PO.FinPlanOrderPO;
import com.dotflat.fin.domain.FinPayAccount;
import com.dotflat.fin.domain.FinPlan;
import com.dotflat.fin.domain.FinPlanOrder;
import com.dotflat.fin.repository.FinPayAccountRepository;
import com.dotflat.fin.service.FinPlanService;
import com.dotflat.fin.service.FinPlanOrderService;
import com.dotflat.rest.controller.RestfulBaseController;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.commons.model.StatusResponse;
import com.matt.commons.page.PagerQuery;
import com.matt.domain.Clientele;
import com.matt.domain.Contract;
import com.matt.domain.ContractProduct;
import com.matt.domain.Product;
import com.matt.foundation.dto.teach.ChildDTO;
import com.matt.foundation.model.ErrorCode;

import com.matt.foundation.utils.CopyUtils;
import com.matt.foundation.vo.ContractVo;
import com.matt.repository.ProductRepository;
import com.matt.repository.base.ContractNativeRepository;
import com.matt.service.ClienteleService;
import com.matt.service.ContractService;
import com.matt.service.TeachCallService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.foundation.constant.CommonConstant.TICKET;


/**
 * @author ：Ron
 * @date ：Created in 11/6/2020 5:07 PM
 */
@RestController
@RequestMapping("/fin/order")
@Slf4j
@Api(tags = "财务 - 待支付账单")
public class FinPlanOrderController extends RestfulBaseController<FinPlanOrder, FinPlanOrderService, FinPlanOrderPO> {

    @Autowired
    public void setBaseService(FinPlanOrderService service){
        this.baseService = service;
    }

    @Autowired
    private FinPlanService finPlanService;

    @Autowired
    private ClienteleService clienteleService;

    @Autowired
    private ContractService contractService;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private TeachCallService teachCallService;

    @Autowired
    private FinPayAccountRepository payAccountRepository;


    @ApiOperation(value = "增加一条记录", hidden = true)
    @Override
    public StatusResponse add(@RequestHeader(TICKET) String ticket, FinPlanOrderPO param){
        return null;
    }

    @ApiOperation(value = "获取一个对象", response = FinPlanOrder.class)
    @GetMapping()
    public StatusResponse get(@RequestHeader(TICKET) String ticket, String id){
        StaffDTO staff = cache.getStaff(ticket);

        FinPlanOrder ret = baseService.get(staff.getAreaId(), staff.getId(), id);

        ContractVo contractVo = contractService.details(ret.getContractId());
        ret.setContract(contractVo);

        return StatusResponse.success(ret);
    }

    @Autowired
    private ContractNativeRepository contractRepository;

    @ApiOperation(value = "获取列表")
    @GetMapping("/list")
    @Override
    public StatusResponse getList(@RequestHeader(TICKET) String ticket, FinPlanOrderPO param, PagerQuery pagerQuery){

        String classId = param.getClassId();
        param.setClassId(null);


        List<ChildDTO> children = null;
        if (StringUtils.isNotBlank(classId)) {
            children = teachCallService.getChildClassList(ticket, 1, param.getChildName(), classId, null);
            List<String> ids = children.stream().map(o->o.getCrmClienteleId()).collect(Collectors.toList());
            param.setClienteleIds(ids);
        }

        StatusResponse res = super.getList(ticket, param, pagerQuery);

        Page<FinPlanOrder> orders = (Page<FinPlanOrder>) res.getData();

        if (orders == null){
            return res;
        }

        //重新获取班级关系
        if (children == null) {
            List<String> ids = orders.getContent().stream().map(o -> o.getClienteleId()).collect(Collectors.toList());
            children = teachCallService.getChildClassList(ticket, 1, param.getChildName(), classId, ids);
        }

        //重新装配班级信息
        if (children != null && children.size() > 0){
            List<ChildDTO> finalChildren = children;
            orders.getContent().stream().forEach(o->{
                Optional<ChildDTO> op = finalChildren.stream().filter(c->o.getClienteleId().equals(c.getCrmClienteleId())).findFirst();
                if (op.isPresent()){
                    ChildDTO child = op.get();
                    o.setClassName(child.getClassNames());
                }
            });
        }
        List<FinPlanOrderPO> ret = orders.getContent().stream().map(o->{
            FinPlanOrderPO po = new FinPlanOrderPO();
            Double totalAmount  = Double.valueOf(o.getTotalAmount())/100;
            o.setTotalAmount(null);
            CopyUtils.copyProperties(o, po);
            po.setTotalAmount(totalAmount);
            return po;
        }).collect(Collectors.toList());
        return   StatusResponse.success(new PageImpl<>(ret, PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize()), orders.getTotalElements()));
    }

    @ApiOperation(value = "增加多条记录")
    @PostMapping("/add_all")
    @Transactional(rollbackOn = RuntimeException.class)
    public StatusResponse addAll(@RequestHeader(TICKET) String ticket, String clienteleIds, FinPlanOrderPO param){
        StaffDTO staff = cache.getStaff(ticket);
        if (StringUtils.isEmpty(param.getPlanId())){
            throw new BusinessException(ErrorCode.PARAM_CAN_NOT_BLANK, "需要指定收费计划");
        }
        if (StringUtils.isEmpty(param.getProducts())){
            return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK, "Products参数不能为空");
        }
        List<ContractProduct> cps = JSON.parseArray(param.getProducts(), ContractProduct.class);

        //校验收费计划
        FinPlan plan = finPlanService.get(staff.getAreaId(), staff.getId(), param.getPlanId());

        List<FinPlanOrder> tmp = new ArrayList<>();
        if(StringUtils.isNotEmpty(param.getContractId())){
            //指定了合同的id
            FinPlanOrder ret = baseService.add(staff.getAreaId(), staff.getId(), param);
            tmp.add(ret);
        }else if(cps != null && cps.size() > 0 && param.getTotalAmount() > 0){
            //单独指定的
            List<String> cIds = null;
            if(StringUtils.isNotEmpty(param.getClienteleId())){
                cIds = new ArrayList<>();
                cIds.add(param.getClienteleId());
            }else if (StringUtils.isNotEmpty(clienteleIds)){
                cIds = JSON.parseArray(clienteleIds, String.class);
            }

            if (cIds == null || cIds.size() == 0){
                throw new BusinessException(ErrorCode.PARAM_CAN_NOT_BLANK, "需要指定客户id");
            }

            //校验支付账号列表
            String payAccountIdsStr;
            if (StringUtils.isNotBlank(param.getPayAccountIds())){
                String[] accountIds = param.getPayAccountIds().split("\\|");

                Set<String> ids = new HashSet<>(Arrays.asList(accountIds));

                List<FinPayAccount> accs = payAccountRepository.findAllByAreaIdAndIdInAndDeletedIsFalse(staff.getAreaId(), ids);

                if (accs.size() != ids.size()){
                    throw new BusinessException(ErrorCode.PRODUCT_NOT_EXIST, "指定账号不存在");
                }

                if (accountIds.length != accs.size()){
                    payAccountIdsStr = ids.stream().collect(Collectors.joining("|"));
                } else {
                    payAccountIdsStr = null;
                }
            } else {
                payAccountIdsStr = null;
            }

            //校验产品列表
            List<String> productIds = cps.stream().map(o->o.getProductId()).collect(Collectors.toList());

            List<Product> products = productRepository.findAllByAreaIdAndIdInAndIsVisible(staff.getAreaId(), productIds, 1 );
            if (products == null || products.size() != products.size()){
                throw new BusinessException(ErrorCode.PRODUCT_NOT_EXIST, "没有找到指定的产品");
            }

//            String productsJSON = JSON.toJSONString(param.getProducts());

            //金额
            Double totalAmount = param.getTotalAmount();
            BigDecimal totalAmount_1 = new BigDecimal(totalAmount).setScale(2,BigDecimal.ROUND_HALF_UP);

            BigDecimal result = totalAmount_1.multiply(BigDecimal.valueOf(100));
            int totalAmount_int = result.intValueExact();

            //需要创建合同
            for (int i = 0; i <cIds.size(); i++){
                String clienteleId = cIds.get(i);

                Clientele clientele = clienteleService.getById(staff.getAreaId(), clienteleId);
                if (clientele == null){
                    throw new BusinessException(ErrorCode.CLIENTELE_EXIST, "指定客户没有找到:" + clienteleId);
                }

                //创建合同
                Contract savedContract = baseService.createContractByPlan(staff, clientele, plan, i,totalAmount_1 , param.getProducts());

                //指定客户
                param.setClienteleId(clienteleId);

                //创建对象
                String finalOrderNO = savedContract.getCode();

                param.setTotalAmount(null);

                FinPlanOrder ret = baseService.add(staff.getAreaId(), staff.getId(), param, o->{
                    o.setPayAccountIds(payAccountIdsStr);

                    o.setTotalAmount(totalAmount_int);

                    o.setOrderSn(finalOrderNO);
                    o.setTitle(savedContract.getName());
                    o.setCreatedByName(staff.getRealName());
                    o.setPlanId(plan.getId());
                    o.setPlanName(plan.getName());
                    o.setContractId(savedContract.getId());
                    o.setChildName(clientele.getSysChildName());
                });

                tmp.add(ret);
            }
            //更新plan的字段
            finPlanService.updateFinPlanCount(plan,true, false);
        }else{
            return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK, "产品列表或合同id不能为空");
        }

        return StatusResponse.success(tmp);
    }

    @RequestMapping(value = "/notify_parent",method = RequestMethod.POST)
    @ApiOperation("通知家长")
    public  StatusResponse notifyParents(@RequestHeader(TICKET) String ticket, String id) {
        StaffDTO staff = cache.getStaff(ticket);

        FinPlanOrder order = baseService.notifyParent(staff.getAreaId(), staff.getId(), id);

        FinPlanOrderPO po = new FinPlanOrderPO();
        Double totalAmount  = Double.valueOf(order.getTotalAmount())/100;
        order.setTotalAmount(null);
        CopyUtils.copyProperties(order, po);
        po.setTotalAmount(totalAmount);

        return StatusResponse.success(po);
    }

    @RequestMapping(value = "/cancel",method = RequestMethod.POST)
    @ApiOperation("作废收费收费单")
    public  StatusResponse cancelPlan(@RequestHeader(TICKET) String ticket, String id) {
        StaffDTO staff = cache.getStaff(ticket);

        FinPlanOrder order = baseService.cancel(staff.getAreaId(), staff.getId(), id);

        FinPlanOrderPO po = new FinPlanOrderPO();
        Double totalAmount  = Double.valueOf(order.getTotalAmount())/100;
        order.setTotalAmount(null);
        CopyUtils.copyProperties(order, po);
        po.setTotalAmount(totalAmount);

        return StatusResponse.success(po);
    }

//    @ApiOperation(value = "增加多条记录")
//    @PostMapping("/add_all1")
//    @Transactional(rollbackOn = RuntimeException.class)
//    public StatusResponse addAll1(@RequestHeader(TICKET) String ticket, String id){
//        StaffDTO staff = cache.getStaff(ticket);
//        //校验收费计划
//        FinPlan plan = finPlanService.get(staff.getAreaId(), staff.getId(), id);
//        System.out.println("校验收费计划-------" + plan);
//        return StatusResponse.success(plan);
//    }

    public static void main(String[] args){
        Double totalAmount = Double.valueOf("19.899999999999999");

        BigDecimal totalAmount_1 = new BigDecimal(totalAmount).setScale(2,BigDecimal.ROUND_HALF_UP);

        System.out.println(totalAmount_1.toString());
    }

}
